`timescale 1ns / 1ps

module axi_slave_int8_test;

// 时钟和复位
reg clk;
reg reset_n;

// AXI Master接口信号
wire [31:0] awaddr;
wire [7:0] awlen;
wire [2:0] awsize;
wire [1:0] awburst;
wire awvalid;
reg awready;

wire [127:0] wdata;
wire [15:0] wstrb;
wire wlast;
wire wvalid;
reg wready;

reg [1:0] bresp;
reg bvalid;
wire bready;

// 用户接口信号
reg start;
reg read_write;
reg [31:0] addr;
reg [7:0] burst_len;
reg [2:0] burst_size;
reg [1:0] burst_type;
reg [127:0] write_data;
reg write_data_valid;
wire write_data_ready;
wire [127:0] read_data;
wire done;
wire error;

// 实例化AXI Master
axi_master #(
    .DATA_WIDTH(128),
    .ADDR_WIDTH(32),
    .BURST_LEN_WIDTH(8)
) axi_master_inst (
    .clk(clk),
    .reset_n(reset_n),
    .awaddr(awaddr),
    .awlen(awlen),
    .awsize(awsize),
    .awburst(awburst),
    .awvalid(awvalid),
    .awready(awready),
    .wdata(wdata),
    .wstrb(wstrb),
    .wlast(wlast),
    .wvalid(wvalid),
    .wready(wready),
    .bresp(bresp),
    .bvalid(bvalid),
    .bready(bready),
    .araddr(),
    .arlen(),
    .arsize(),
    .arburst(),
    .arvalid(),
    .arready(1'b0),
    .rdata(128'h0),
    .rresp(2'b00),
    .rlast(1'b0),
    .rvalid(1'b0),
    .rready(),
    .start(start),
    .read_write(read_write),
    .addr(addr),
    .burst_len(burst_len),
    .burst_size(burst_size),
    .burst_type(burst_type),
    .write_data(write_data),
    .write_data_valid(write_data_valid),
    .write_data_ready(write_data_ready),
    .read_data(read_data),
    .done(done),
    .error(error)
);

// 实例化AXI Slave
axi_slave #(
    .DATA_WIDTH(128),
    .ADDR_WIDTH(32)
) axi_slave_inst (
    .ACLK(clk),
    .ARESETN(reset_n),
    .AWADDR(awaddr),
    .AWLEN(awlen),
    .AWSIZE(awsize),
    .AWBURST(awburst),
    .AWVALID(awvalid),
    .AWREADY(awready),
    .WDATA(wdata),
    .WSTRB(wstrb),
    .WLAST(wlast),
    .WVALID(wvalid),
    .WREADY(wready),
    .BRESP(bresp),
    .BVALID(bvalid),
    .BREADY(bready),
    .ARADDR(32'h0),
    .ARLEN(8'h0),
    .ARSIZE(3'h0),
    .ARBURST(2'h0),
    .ARVALID(1'b0),
    .ARREADY(),
    .RDATA(),
    .RRESP(),
    .RLAST(),
    .RVALID(),
    .RREADY(1'b0)
);

// 时钟生成
initial begin
    clk = 0;
    forever #5 clk = ~clk;  // 100MHz时钟
end

// 从int8.coe文件中提取的测试数据 (前96个128位数据，每两个64位数据合并为一个128位)
reg [127:0] test_data [0:95];  // 192个64位数据合并为96个128位数据

initial begin
    // 从int8.coe文件中提取的数据，每两个64位数据合并为一个128位
    // 第1-2行合并
    test_data[0]  = {64'h25095ce6b539265b, 64'h84f5191992b34329};
    test_data[1]  = {64'h2253fc8678538ab6, 64'h4941f3c57e7a942e};
    test_data[2]  = {64'h4856a66f33f6934e, 64'hc459caff4d76f9b9};
    test_data[3]  = {64'h66f33088dafeef4a, 64'h060561d6ef40a910};
    test_data[4]  = {64'h9484a9821b836412, 64'h990c84ceb326c215};
    test_data[5]  = {64'h87680c463b37a009, 64'h6b94cd360d0c50da};
    test_data[6]  = {64'hc3f49e8f945ff4da, 64'hc67bc37d47d8b1f3};
    test_data[7]  = {64'hc354ebc03811ca91, 64'hf5c2b8948d25f678};
    test_data[8]  = {64'hc86f65a6c1b6a00b, 64'h70afea4b088ac7b4};
    test_data[9]  = {64'h823ea75e80000000, 64'h93773cdc90fd933f};
    test_data[10] = {64'hd64241ccb2d3f9f6, 64'hb9c3af671a688c30};
    test_data[11] = {64'hcffbe0da358db47f, 64'h274191cf28ff75b8};
    test_data[12] = {64'h717762af9087e062, 64'h49bd66365894ca30};
    test_data[13] = {64'h69bd5662909eb865, 64'hd87bb7cfd4e4fd41};
    test_data[14] = {64'h429b0fa1e47651be, 64'h8998424daeb54307};
    test_data[15] = {64'ha1bd6f44031b9bb1, 64'h6e8ec88968e7047b};
    test_data[16] = {64'hac10fd8e945441b6, 64'h16d30a5f98a8276d};
    test_data[17] = {64'hec924e3a564f8d57, 64'hf722c0e33e7567e9};
    test_data[18] = {64'h9f44f5c69b31ece6, 64'hf1f8648da111e75a};
    test_data[19] = {64'h8d01858b153dec6d, 64'h7169795984b2d93f};
    test_data[20] = {64'h2456ec07dbff4a47, 64'h1b2288f0032ac091};
    test_data[21] = {64'hf0e557023f0e4211, 64'h262e2e3d80000000};
    test_data[22] = {64'h846af840d9d8dc7c, 64'hd1c8a3a36f41c070};
    test_data[23] = {64'h1102833d35fc87f8, 64'h2ad49af5f7f5f6d4};
    test_data[24] = {64'h9fa98f434f69ed10, 64'hc5d821b2c3f57dc7};
    test_data[25] = {64'h412d0bc07b32db17, 64'hb4c29d715842152b};
    test_data[26] = {64'he5d92bb4796ed5e2, 64'h5323041654701145};
    test_data[27] = {64'h7d45d470c7d01f59, 64'h2bff319c0f7e6c3f};
    test_data[28] = {64'hb74d7413a8e4fc74, 64'h1de0282351796ea7};
    test_data[29] = {64'h7a8c15414b3f1b5c, 64'h49918eeae9e3ea74};
    test_data[30] = {64'h97ba6e46f5b491f8, 64'h56e4d238c47c4563};
    test_data[31] = {64'h861cd71b23e56da9, 64'hcc55fb289f7bb8b5};
    test_data[32] = {64'h76105d98a2a69342, 64'h0c4f7e52775b5a58};
    test_data[33] = {64'h1a7c1cf2e9c4aa3c, 64'h28fcedf4abfc8143};
    test_data[34] = {64'h091187c18c5ccf54, 64'h821e61005ba78184};
    test_data[35] = {64'h5a1ef75c5032968c, 64'h13091b00820e2d02};
    test_data[36] = {64'h6f0b0f1ad6f90c03, 64'heb4234701b01d5d0};
    test_data[37] = {64'h680673b0e1bf4309, 64'he5b562eec8efb137};
    test_data[38] = {64'h9b0daf3738cc56e4, 64'h232d77b212ab089a};
    test_data[39] = {64'h6286b0b394ae20ce, 64'h47632c0171b7d249};
    test_data[40] = {64'h62b645de8c76beea, 64'h3cccc4e95a203c8f};
    test_data[41] = {64'hae80c90e91af3681, 64'h9aa513c30c60fac6};
    test_data[42] = {64'h1ba7cf9a2d24471b, 64'h25d9fdfaf2282f30};
    test_data[43] = {64'hbfa774b889c5395e, 64'h5b617dd19d1dc72a};
    test_data[44] = {64'h7ddae3880d1c4dbc, 64'hafc1946dd6cee341};
    test_data[45] = {64'hf67abd592d19e38c, 64'h70ae9d069691e3b6};
    test_data[46] = {64'hf7fd5869cd6fb652, 64'h5bbdb69fa7696f26};
    test_data[47] = {64'h1885efc0c6304c91, 64'h351175a8bf746925};
    test_data[48] = {64'h4696552a109e66c7, 64'h104232d4c8202f72};
    test_data[49] = {64'hfe83ac58cae86427, 64'h0e6506c016b030ee};
    test_data[50] = {64'h74f2c4c034fbe5df, 64'h82fecb078312e008};
    test_data[51] = {64'he16d548e845f01cf, 64'h11749d9f1223292f};
    test_data[52] = {64'h7ccace6e81f51cde, 64'hb9b358ed4e0176be};
    test_data[53] = {64'hc2c105efb2ff4433, 64'h761bff435e87e55e};
    test_data[54] = {64'h8e671e31142a4f2f, 64'h8db744703e892fd8};
    test_data[55] = {64'h200c2b5ffd85bfec, 64'h7398ff4444c42819};
    test_data[56] = {64'h253a7e26a8c880d4, 64'hc74e2fe17486fc55};
    test_data[57] = {64'h9267e74245fead5f, 64'h288053a5331a4315};
    test_data[58] = {64'h48a1349da8388d8f, 64'h1fb726b1e06317d6};
    test_data[59] = {64'h7a7969e978d0bed0, 64'ha95764fb41065a54};
    test_data[60] = {64'h61069f094cb1bfa0, 64'h97580c889d7bb5c6};
    test_data[61] = {64'h85f64f3183a4ab17, 64'h2134cc99e001f61d};
    test_data[62] = {64'heb756782d8b7cc5d, 64'h731d92bad0ebc692};
    test_data[63] = {64'ha43cccd4c9ca923f, 64'h1b877b09e33e493c};
    // B矩阵数据开始 (64'h50176594e180367f)    heddc1b2bf2937d7d, 64'
    test_data[64] = {64'he0176594e180367f, 64'h5ddc1b2bf2937d7d};
    test_data[65] = {64'h0083e2aa6c80447f, 64'h18b8a6848df1abb3};
    test_data[66] = {64'h80056d751d80d17f, 64'h7533cbc490b4babc};
    test_data[67] = {64'hf657f540a8801c7f, 64'h16344eef1a0ab68d};
    test_data[68] = {64'h1b1d9cdd7780e87f, 64'h66423873c73e63f1};
    test_data[69] = {64'h5e650811cb80c67f, 64'h7ef744ae32f3f61c};
    test_data[70] = {64'h112ccd4ec380ba7f, 64'hf35bacd50e438454};
    test_data[71] = {64'hdcf1fcf3b380e17f, 64'hd46bb89f1130bfcf};
    test_data[72] = {64'h8be03a281280d37f, 64'hac6051e8a0447e3a};
    test_data[73] = {64'h5942f0886a80a27f, 64'h25b6c109d100b01f};
    test_data[74] = {64'h40570873ae80ae7f, 64'hb005a908d0853e23};
    test_data[75] = {64'h8bf3f0b40780d07f, 64'hcb467232712ac7b1};
    test_data[76] = {64'h397a00fe5380007f, 64'h9c94d15bcaee29fd};
    test_data[77] = {64'h1bedc8bfef80ff7f, 64'h1c8968259f2672d8};
    test_data[78] = {64'h88e164a0e480927f, 64'hf0f36e6306518f1b};
    test_data[79] = {64'hdb0216591d80e77f, 64'h7f2801813e8ed484};
    // A矩阵数据开始 (64'hfc47877939015c55)    h553fb6d2e6a85f40, 64'
    test_data[80] = {64'h5c47877939015c55, 64'hf53fb6d2e6a85f40};
    test_data[81] = {64'hc41d5be0e20b2666, 64'h8080808080808080};
    test_data[82] = {64'h11f9de99d3dbbb63, 64'ha241416dca400c88};
    test_data[83] = {64'h931646c2a502507c, 64'h8080808080808080};
    test_data[84] = {64'ha4c1c7e66e452d87, 64'hd03b095d6e8e1745};
    test_data[85] = {64'h062021d9dead896b, 64'hbd924b2883d2ae68};
    test_data[86] = {64'h0069bcaf497cf808, 64'h6531608b56726dab};
    test_data[87] = {64'h875b86a53153a475, 64'h44fd5b7f4b43c83a};
    test_data[88] = {64'hd27460de43bd947b, 64'hd7e0fa0c3bbf96b1};
    test_data[89] = {64'h71c98550a54dc3de, 64'haaba4d95be5b506b};
    test_data[90] = {64'h0cb5384de43e3b55, 64'h632d0d1e6472d012};
    test_data[91] = {64'ha249e515e3f9e98a, 64'h51a64b0044b0a949};
    test_data[92] = {64'h0761700dd916f611, 64'ha518fcf8a024b9ac};
    test_data[93] = {64'h766c2667818a4cf5, 64'hcce043bf09a8a189};
    
    $display("测试数据已加载，共96个128位数据");
    $display("数据来源：int8.coe文件（每两个64位数据合并为一个128位）");
end

// 测试过程
reg [7:0] data_index;  // 改为8位以支持96个数据

initial begin
    // 初始化
    reset_n = 0;
    start = 0;
    read_write = 0;
    addr = 0;
    burst_len = 0;
    burst_size = 0;
    burst_type = 0;
    write_data = 0;
    write_data_valid = 0;
    data_index = 0;
    
    // 复位
    #100;
    reset_n = 1;
    #50;
    
    // 开始写测试
    $display("开始AXI Slave写入int8.coe数据测试...");
    $display("使用int8.coe文件中的前192个64位数据合并为96个128位数据");
    
    // 配置写参数
    addr = 32'h1000;           // 起始地址
    burst_len = 8'd96;         // 96次突发（128位）
    burst_size = 3'b100;       // 128位 (16字节)
    burst_type = 2'b01;        // INCR突发类型
    read_write = 0;            // 写操作
    
    // 启动传输
    start = 1;
    #10;
    start = 0;
    
    // 发送测试数据
    data_index = 0;
    while (data_index < 96) begin
        if (write_data_ready) begin
            write_data = test_data[data_index];
            write_data_valid = 1;
            data_index = data_index + 1;
            if (data_index % 16 == 0) begin
                $display("已发送 %d 个128位数据", data_index);
            end
        end
        #10;
    end
    write_data_valid = 0;
    
    // 等待传输完成
    wait (done);
    #100;
    
    if (error) begin
        $display("错误：传输失败！");
    end else begin
        $display("成功：96次突发写传输完成！");
        $display("所有数据都来自int8.coe文件（128位格式）");
        $display("数据已通过AXI Slave写入RAM");
    end
    
    // 验证写入的数据
    $display("验证写入的数据...");
    for (integer i = 0; i < 96; i = i + 16) begin
        #10;
        $display("地址范围 0x%x-0x%x 包含数据: 0x%032x 到 0x%032x", 
                32'h1000 + i*16, 32'h1000 + (i+15)*16, test_data[i], test_data[i+15]);
    end
    
    $finish;
end

// 监控信号 - 修正后的版本
reg [7:0] write_counter;  // 添加写计数器来跟踪传输进度

always @(posedge clk) begin
    if (!reset_n) begin
        write_counter <= 0;
    end else if (wvalid && wready) begin
        if (wlast) begin
            write_counter <= 0;  // 重置计数器
        end else begin
            write_counter <= write_counter + 1;
        end
    end
end

always @(posedge clk) begin
    if (awvalid && awready) begin
        $display("时间 %0t: AXI写地址 0x%x, 长度 %d", $time, awaddr, awlen);
    end
    
    if (wvalid && wready) begin
        if (write_counter == 0 || write_counter == 95 || wlast) begin
            $display("时间 %0t: AXI写数据 0x%032x, wlast=%b, 计数器=%d", $time, wdata, wlast, write_counter);
        end
    end
    
    if (bvalid && bready) begin
        $display("时间 %0t: AXI写响应完成, bresp=%b", $time, bresp);
    end
end

// 波形输出
initial begin
    $dumpfile("axi_slave_int8_test.vcd");
    $dumpvars(0, axi_slave_int8_test);
end

endmodule